#include "ints.h"
#include <stdio.h>

int install_asm_irq_handler(int irq, void (*irq_func)(void),
				_go32_dpmi_seginfo *old_irq)
{
	//devolve o vector correspondente ao IRQ pretendido
	int vector = IRQ_VECTOR(irq);
	
	//obter endereco do handler original
	if(_go32_dpmi_get_protected_mode_interrupt_vector(vector, old_irq)) return -1;
	
	//variavel para o endereco do novo handler
	_go32_dpmi_seginfo new_irq;
	new_irq.pm_selector = _go32_my_cs(); // selector do codigo
	new_irq.pm_offset = (unsigned long)irq_func; // endereco do novo handler
	
	//instalacao do handler na IDT
	if(_go32_dpmi_set_protected_mode_interrupt_vector(vector, &new_irq)) return -1;
	return 0;
}


int install_c_irq_handler(int irq, void (*irq_func)(void),
			    _go32_dpmi_seginfo *old_irq)
{
	//devolve o vector correspondente ao IRQ pretendido
	int vector = IRQ_VECTOR(irq);
	
	//endereco do handler original
	if(_go32_dpmi_get_protected_mode_interrupt_vector(vector, old_irq)) return -1;
	
	//variavel para o endereco do handler
	_go32_dpmi_seginfo new_irq;
	new_irq.pm_selector = _go32_my_cs(); // selector do codigo
	new_irq.pm_offset = (unsigned long)irq_func; // endereco do novo handler
	
	//prepara fun��o assembly para chamar fun��o C
	if(_go32_dpmi_allocate_iret_wrapper(&new_irq)) return -1;
	
	// instalacao do handler na IDT
	if(_go32_dpmi_set_protected_mode_interrupt_vector(vector, &new_irq)) return -1;
	return 0;
}


void reinstall_asm_irq_handler(int irq, _go32_dpmi_seginfo *old_irq)
{
	//devolve o vector correspondente ao IRQ pretendido
	int vector = IRQ_VECTOR(irq);
	
	//repoe o handler original
	_go32_dpmi_set_protected_mode_interrupt_vector(vector, old_irq);
}


void reinstall_c_irq_handler(int irq, _go32_dpmi_seginfo *old_irq)
{
	//devolve o vector correspondente ao IRQ pretendido
	int vector = IRQ_VECTOR(irq);
	
	//guarda apontador para o handler actual
	_go32_dpmi_seginfo new_irq;
	_go32_dpmi_get_protected_mode_interrupt_vector(vector, &new_irq);
	
	//repoe o handler original
	_go32_dpmi_set_protected_mode_interrupt_vector(vector, old_irq);
	
	//liberta fun��o assembly
	_go32_dpmi_free_iret_wrapper(&new_irq);
}


void mask_pic(int irq)
{
	unsigned short pic;
	
	if (irq < 8)
		pic = PIC1_MASK;
	else
		pic = PIC2_MASK;
	
	unsigned char mascara = inportb(pic) | IRQ_MASK_BIT(irq); 
	outportb(pic, mascara); 
}

void unmask_pic(int irq)
{
	unsigned short pic;
	
	if (irq <= 7) 
		pic = PIC1_MASK;
	else
		pic = PIC2_MASK;
		
	unsigned char mascara = inportb(pic) & (~IRQ_MASK_BIT(irq));
	outportb(pic, mascara); 
}

void set_ints(Bool on)
{
	static Byte state_pic1;
	static Byte state_pic2;
	
	if(on)
	{
		outportb(PIC1_MASK, state_pic1);
		outportb(PIC2_MASK, state_pic2);
	}
	else
	{
		state_pic1 = inportb(PIC1_MASK);
		state_pic2 = inportb(PIC2_MASK);
		outportb(PIC1_MASK, 0xFF);
		outportb(PIC2_MASK, 0xFF);
	}
}

Byte get_pic1() {
	return inportb(PIC1_MASK);
}


Byte get_pic2() {
	return inportb(PIC2_MASK);
}


void set_pic_var(Byte pic1, Byte pic2)
{
	outportb(PIC1_MASK, pic1);
	outportb(PIC2_MASK, pic2);
}


void mask_pic_var(int irq, Byte* pic1, Byte* pic2)
{
	Byte* pic;
	
	if (irq < 8) pic = pic1;
	else pic = pic2;
	
	(*pic) |= IRQ_MASK_BIT(irq);
}


void unmask_pic_var(int irq, Byte* pic1, Byte* pic2)
{
	Byte* pic;
	
	if (irq < 8) pic = pic1;
	else pic = pic2;
	
	(*pic) &= (~IRQ_MASK_BIT(irq));
}

